/*
   @Copyright:LibreOJ
   @Author:   tjyemail
   @Problem:  https://loj.ac/problem/102
   @Language: C++
   @Datetime: 20-08-19 14:07
   */
// Dinic with Shortest Path Fast Algorithm (SPFA) , time 2531ms

#include <bits/stdc++.h>
using namespace std;

#define VERTEX 405
#define EDGE 15005
// linked forward star
struct Edge {
	int v, cap, price, next; // cost = cap * price
	Edge(int v=0, int cap=0, int price=0, int next=-1):v(v), cap(cap), price(price), next(next){}
} edges[EDGE*2];
int heads[VERTEX], curs[VERTEX]; // current available edge position
int ie = 0;
inline void add(int u, int v, long long cap, long long price) {
	edges[ie] = Edge(v, cap, price, heads[u]);
	heads[u] = ie++;
	// 1) reverse edge position must be ie+1
	// 2) edges position must from 0 => heads must initialize as -1
	// so, the reverse edge position is ie^1.
	edges[ie] = Edge(u, 0, -price, heads[v]); // reverse edge
	heads[v] = ie++;
}
bool visited[VERTEX];
int costs[VERTEX]; // s->k cost

bool spfa(int v, int s, int t) {
	for(int i=0; i++<v; costs[i]=INT_MAX);
	costs[s] = 0;
	queue<int> vs;
	for(vs.push(s); !vs.empty(); vs.pop()) {
		s = vs.front();
		for(int k=heads[s]; k!=-1; k=edges[k].next) {
			if (edges[k].cap>0 && costs[edges[k].v] > costs[s]+edges[k].price) {
				costs[edges[k].v] = costs[s]+edges[k].price;
				vs.push(edges[k].v);
			}
		}
	}
	return costs[t]!=INT_MAX; // check if it has path s -> t
}

int dfs(int s, int t, int cap=INT_MAX) {
	if (cap==0 || s==t) return cap;
	int flow = 0, cur = 0;
	visited[s] = true;
	for(int k=curs[s]; k!=-1 && flow!=cap; k=edges[k].next) {
		curs[s] = k; // record current available edge position
		// make sure all the arguement paths are Shortest Path
		if (visited[edges[k].v] || costs[edges[k].v]!=costs[s]+edges[k].price) continue;
		cur = dfs(edges[k].v, t, min(cap-flow, edges[k].cap));
		if (cur==0) continue;
		edges[k].cap -= cur;
		edges[k^1].cap += cur;
		flow += cur;
	}
	visited[s] = false;
	return flow;
}

void minicost(int v, int s, int t) {
	int flow = 0, f = 0, cost = 0;
	while(spfa(v, s, t)) { // found shortest path
		// update available capacity flow
		memcpy(curs, heads, sizeof(int)*(v+1));
		f = dfs(s, t);
		flow += f;
		cost += f*costs[t];
	}
	printf("%d %d\n", flow, cost);
}

int main()
{
	int v, e, a, b, c, p; // vertex, edge
	scanf("%d %d", &v, &e);
	memset(heads, -1, sizeof(heads));
	for(int i=0; i++<e; ) {
		scanf("%d %d %d %d", &a, &b, &c, &p); // a->b, capacity, price
		add(a, b, c, p);
	}
	minicost(v, 1, v);
	return 0;
}
